package org.fone.utils.task;

import cn.hutool.core.util.ArrayUtil;
import com.sun.org.apache.bcel.internal.generic.BREAKPOINT;
import org.fone.pojo.Table;
import org.fone.pojo.TableField;
import org.fone.utils.task.data.Operator;
import cn.hutool.core.util.ObjectUtil;
import org.fone.pojo.Table;
import org.fone.utils.task.data.Operator;
import org.fone.utils.task.data.SeniorType;
import org.fone.utils.task.data.TableFieldType;
import org.springframework.util.ObjectUtils;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static cn.hutool.core.lang.Console.log;
//编辑表格工具类
public class TableEditor {
    public static Table numberFilter(Table table,String field, String op,Long value){
        List<Map<String, Object>> lines = table.getTableLines();
        Operator operator = Operator.getTypeByValue(op);
        System.out.println(operator);
        log("numberFilter:",field,op,value);
        switch (operator){
            case OP_EQUALS:
                for (int i=0;i<lines.size();){
                    if (ObjectUtils.isEmpty(lines.get(i).get(field))) continue;
                    if (value!=Long.parseLong(lines.get(i).get(field).toString()))
                        lines.remove(i);
                    else i++;
                }
                break;
            case OP_GREATER:
                for (int i=0;i<lines.size();){
                    if (ObjectUtils.isEmpty(lines.get(i).get(field))) continue;
                    if (value >= Long.parseLong(lines.get(i).get(field).toString()))
                        lines.remove(i);
                    else i++;
                }
                break;
            case OP_LESS:
                for (int i=0;i<lines.size();){
                    if (ObjectUtils.isEmpty(lines.get(i).get(field))) continue;
                    if (value <= Long.parseLong(lines.get(i).get(field).toString()))
                        lines.remove(i);
                    else i++;
                }
                break;
            case OP_GREATER_EQUALS:
                for (int i=0;i<lines.size();){
                    if (ObjectUtils.isEmpty(lines.get(i).get(field))) continue;
                    if (value > Long.parseLong(lines.get(i).get(field).toString()))
                        lines.remove(i);
                    else i++;
                }
                break;
            case OP_LESS_EQUALS:
                for (int i=0;i<lines.size();){
                    if (ObjectUtils.isEmpty(lines.get(i).get(field))) continue;
                    if (value < Long.parseLong(lines.get(i).get(field).toString()))
                        lines.remove(i);
                    else i++;
                }
                break;
        }

        return table;
    }

    public static Table strFilter(Table table,String field, String op,String value) {
        List<Map<String, Object>> lines = table.getTableLines();
        Operator operator = Operator.getTypeByValue(op);
        switch(operator){
            case OP_EQUALS:
                for (int i=0;i<lines.size();){
                    if (ObjectUtils.isEmpty(lines.get(i).get(field))) continue;
                    if (!lines.get(i).get(field).toString().equals(value))
                        lines.remove(i);
                    else i++;
                }
                break;
            case OP_CONTAINS:
                for (int i=0;i<lines.size();){
                    if (ObjectUtils.isEmpty(lines.get(i).get(field))) continue;
                    if (!lines.get(i).get(field).toString().contains(value))
                        lines.remove(i);
                    else i++;
                }
                break;
            case OP_NOT_CONTAINS:
                for (int i=0;i<lines.size();){
                    Map<String, Object> line = lines.get(i);
                    if (ObjectUtils.isEmpty(line.get(field))) continue;
                    if (line.get(field).toString().contains(value))
                        lines.remove(i);
                    else i++;
                }
                break;
            case OP_REGEX:
                for (int i=0;i<lines.size();){
                    Map<String, Object> line = lines.get(i);
                    if (ObjectUtils.isEmpty(line.get(field))) continue;
                    if (!line.get(field).toString().matches(value))
                        lines.remove(i);
                    else i++;
                }
                break;
        }
        return table;
    }

    public static Table dateFilter(Table table,String field, String op,String value){

        try {
            List<Map<String, Object>> lines = table.getTableLines();
            Operator operator = Operator.getTypeByValue(op);
            String[] split = value.split("-");
            long startTime = Long.parseLong(split[0]);
            long endTime = Long.parseLong(split[1]);
            for (int i = 0; i < lines.size();) {
    //                Long time = new SimpleDateFormat("yyyy-MM-dd").parse(lines.get(i).get(field).toString()).getTime();
                if (ObjectUtils.isEmpty(lines.get(i).get(field))) continue;

                long time = ((Date)lines.get(i).get(field)).getTime();
                if ((time < startTime) || (time> endTime)) {
                    lines.remove(i);
                } else {
                    i++;
                }
            }
            System.out.println("table = " + table);

            return table;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private static int findLine(List<Map<String, Object>> lines,Map<String,String> kvs){
        for (int i=0;i<lines.size();++i){
            Map<String, Object> line = lines.get(i);
            boolean flag=true;
            for (String key:kvs.keySet()){
                if (!line.containsKey(key)) return -1;
                if (ObjectUtils.isEmpty(line.get(key))) return -1;
                if (!line.get(key).toString().equals(kvs.get(key))) {
                    flag = false;
                    break;
                }
            }
            if (flag) return i;
        }
        return -1;
    }

    /**
     * 合并
     * @param table1
     * @param table2
     * @param match_relationship
     * @param out_fields
     * @return
     */
    public static Table merger(Table table1, Table table2,boolean union,Map<String,String> match_relationship,List<String[]> out_fields,List<Integer> source_ids) {
        LinkedList<Map<String, Object>> lines = new LinkedList<>();
        List<Map<String, Object>> lines1 = table1.clone().getTableLines();//会修改数据
        List<Map<String, Object>> lines2 = table2.clone().getTableLines();//会修改数据
        ArrayList<String[]> tab1_fields = new ArrayList<>();
        ArrayList<String[]> tab2_fields = new ArrayList<>();
        String id1 = source_ids.get(0).toString();

        out_fields.forEach(fields -> {
            if (id1.equals(fields[0]))
                tab1_fields.add(new String[]{fields[1], "".endsWith(fields[2]) ? fields[1] : fields[2]});
            else
                tab2_fields.add(new String[]{fields[1], "".endsWith(fields[2]) ? fields[1] : fields[2]});
        });

        for (Map<String, Object> line2:lines2){
            Map<String, String> kvs = new HashMap<>();
            for (String k1 : match_relationship.keySet()) {
                if (ObjectUtils.isEmpty(line2.get(match_relationship.get(k1)))) kvs.put(k1, null);
                else kvs.put(k1, line2.get(match_relationship.get(k1)).toString());
            }
            int index = findLine(lines1, kvs);
            Map<String, Object> line = new HashMap<>();

            if (index == -1) {//新增行
                if (!union) continue;
                for (String[] field : tab1_fields)
                    line.put(field[1], line2.get(field[0]));
                for (String[] field : tab2_fields)//直接插入
                    line.put(field[1], line2.get(field[0]));
            } else {
                //合并index行
                Map<String, Object> line1 = lines1.get(index);
                for (String[] field : tab1_fields)
                    line.put(field[1], line1.get(field[0]));
                for (String[] field : tab2_fields)//直接插入
                    line.put(field[1], line2.get(field[0]));
                lines1.remove(index);
//                lines2.remove(line2);
            }
            lines.add(line);
        }
        for (Map<String, Object> line1:lines1){
            //tab1的key，tab2的value
            System.out.println("line1 = " + line1);
            Map<String, String> kvs = new HashMap<>();
            for (String k1 : match_relationship.keySet()) {
                if (ObjectUtils.isEmpty(line1.get(k1))) kvs.put(match_relationship.get(k1), null);
                else kvs.put(match_relationship.get(k1), line1.get(k1).toString());
            }
            int index = findLine(lines2, kvs);
            Map<String, Object> line = new HashMap<>();
            if (index == -1) {//新增行
                if (!union) continue;
                for (String[] field : tab1_fields)
                    line.put(field[1], line1.get(field[0]));
                for (String[] field : tab2_fields)//直接插入
                    line.put(field[1], line1.get(field[0]));
            } else {
                //合并index行
                Map<String, Object> line2 = lines2.get(index);
                for (String[] field : tab1_fields)
                    line.put(field[1], line1.get(field[0]));
                for (String[] field : tab2_fields)//直接插入
                    line.put(field[1], line2.get(field[0]));
                lines2.remove(index);
//                lines1.remove(line1);
            }
            lines.add(line);
        }
        //新tab
        List<TableField> tableFields = new ArrayList<>();
        Map<String, String> field_type = new HashMap<>();
        table1.getTableFields().forEach(tableField -> field_type.put(tableField.getColumn_name(), tableField.getData_type()));
        table2.getTableFields().forEach(tableField -> field_type.put(tableField.getColumn_name(), tableField.getData_type()));
        for (String[] field : tab1_fields)
            tableFields.add(new TableField(field[1], field_type.get(field[0])));
        for (String[] field : tab2_fields)//直接插入
            tableFields.add(new TableField(field[1], field_type.get(field[0])));
        LinkedList<Map<String, Object>> tableLines = new LinkedList<>();
        return new Table(table1.getTableName() + "-" + table2.getTableName(), tableFields, lines);
    }
    public static Table addColumnValue(Table table, SeniorType operator, TableFieldType field_type, String field, String value) {
        List<Map<String, Object>> lines = table.getTableLines();
        switch (field_type) {
            case NUMBER:
                for (Map<String, Object> line : lines) {
                    if (ObjectUtils.isEmpty(line.get(field))) continue;
                    double v = Double.parseDouble(value);
                    double f = Double.parseDouble(line.get(field).toString());
                    line.put(field, f + v);
                }
                break;
            case STR:
                switch (operator) {
                    case ADD_LEFT:
                        for (Map<String, Object> line : lines) {
                            if (ObjectUtils.isEmpty(line.get(field))) continue;
                            line.put(field, value + line.get(field));
                        }
                        break;
                    case ADD_RIGHT:
                        for (Map<String, Object> line : lines) {
                            if (ObjectUtils.isEmpty(line.get(field))) continue;
                            line.put(field, line.get(field) + value);
                        }
                        break;
                }
                break;
        }
        return table;
    }

    public static Table subColumnValue(Table table, TableFieldType field_type, String field, String value) {
        List<Map<String, Object>> lines = table.getTableLines();
        Table oldTable = table;
        if (ObjectUtil.isEmpty(lines.get(0).get(field))) return null;
        switch (field_type) {
            case NUMBER:
                for (Map<String, Object> line : lines) {
                    if (ObjectUtils.isEmpty(line.get(field))) continue;
                    double v = Double.parseDouble(value);
                    double f = Double.parseDouble(line.get(field).toString());
                    line.put(field, f - v);
                }
                break;
            case STR:
                for (Map<String, Object> line : lines) {
                    if (ObjectUtils.isEmpty(line.get(field))) continue;
                    line.put(field, line.get(field).toString().replaceAll(value, ""));
                }
                break;
        }
        return table;
    }

    public static Table insertColumn(Table table, TableFieldType field_type, String field, String value) {
        List<Map<String, Object>> lines = table.getTableLines();
        table.getTableFields().add(0,new TableField(field,"number"));
        int val = Integer.parseInt(value);
        for (Map<String, Object> line : lines) {
            line.put(field, val++);
        }
        return table;
    }
}
